﻿/*
·´`·.¸.»------------------------------------------------------------ë·´`·.¸.»
        File: GaussianBlur.cs
        Project: Themaopdracht 7
        Author: Felix Mann

        Description:
        This is a simple Gaussian Blur
·´`·.¸.»------------------------------------------------------------ë·´`·.¸.»
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace THO7_Team8
{
    class GaussianBlur : VisionAlgorithm
    {
        public GaussianBlur(String name) : base(name) { }
        /// <summary>
        /// Runs a Gaussian Blur algorithm on the provided image.
        /// </summary>
        /// <param name="sourceImage">The image to process</param>
        /// <returns>The processed bitmap</returns>
        public unsafe override System.Drawing.Bitmap DoAlgorithm(System.Drawing.Bitmap sourceImage)
        {
            Bitmap returnImage = new Bitmap(sourceImage);
            BitmapData sourceImageData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData returnImageData = returnImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            unsafe
            {
                byte weight = 99;

                byte* pointer = (byte*)sourceImageData.Scan0.ToPointer() + 2 * sourceImageData.Stride + 6;
                byte* pointer2 = (byte*)returnImageData.Scan0.ToPointer() + 2 * returnImageData.Stride + 6;

                for (int y = 0; y < sourceImageData.Height - 4; y++)
                {
                    for (int x = 0; x < sourceImageData.Width - 4; x++)
                    {
                        int resultB = 0;
                        int resultG = 0;
                        int resultR = 0;

                        //////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////
                        resultB += (*(pointer - sourceImageData.Stride - 3) * 9);
                        resultG += (*(pointer - sourceImageData.Stride - 2) * 9);
                        resultR += (*(pointer - sourceImageData.Stride - 1) * 9);

                        resultB += (*(pointer - sourceImageData.Stride) * 12);
                        resultG += (*(pointer - sourceImageData.Stride + 1) * 12);
                        resultR += (*(pointer - sourceImageData.Stride + 2) * 12);

                        resultB += (*(pointer - sourceImageData.Stride + 3) * 9);
                        resultG += (*(pointer - sourceImageData.Stride + 4) * 9);
                        resultR += (*(pointer - sourceImageData.Stride + 5) * 9);
                        //////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////
                        resultB += (*(pointer - 3) * 12);
                        resultG += (*(pointer - 2) * 12);
                        resultR += (*(pointer - 1) * 12);

                        resultB += (*(pointer) * 15);
                        resultG += (*(pointer + 1) * 15);
                        resultR += (*(pointer + 2) * 15);

                        resultB += (*(pointer + 3) * 12);
                        resultG += (*(pointer + 4) * 12);
                        resultR += (*(pointer + 5) * 12);
                        //////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////
                        resultB += (*(pointer + sourceImageData.Stride - 3) * 9);
                        resultG += (*(pointer + sourceImageData.Stride - 2) * 9);
                        resultR += (*(pointer + sourceImageData.Stride - 1) * 9);

                        resultB += (*(pointer + sourceImageData.Stride) * 12);
                        resultG += (*(pointer + sourceImageData.Stride + 1) * 12);
                        resultR += (*(pointer + sourceImageData.Stride + 2) * 12);

                        resultB += (*(pointer + sourceImageData.Stride + 3) * 9);
                        resultG += (*(pointer + sourceImageData.Stride + 4) * 9);
                        resultR += (*(pointer + sourceImageData.Stride + 5) * 9);
                        //////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////

                        resultB /= weight;
                        resultG /= weight;
                        resultR /= weight;


                        pointer2[0] = (byte)resultB;
                        pointer2[1] = (byte)resultG;
                        pointer2[2] = (byte)resultR;

                        pointer += 3;
                        pointer2 += 3;
                    }
                    pointer += 12;
                    pointer2 += 12;
                }
            }

            sourceImage.UnlockBits(sourceImageData);
            returnImage.UnlockBits(returnImageData);
            return returnImage;
        }
    }
}
